#include "fyp/ObjectManager.h"

//------------------------------------------------------------------------------
// additional header includes
#include "fyp/render/Factory.h"
#include "fyp/render/Renderer.h"
#include "fyp/render/Renderable.h"
#include "fyp/render/Texture.h"
#include "fyp/ResourcePool.h"

#include "fyp/core/MatrixUtil.h"

using namespace ming::fyp::render;

//------------------------------------------------------------------------------
namespace ming
{
namespace fyp
{
	//--------------------------------------------------------------------------
	TObjectManager::TObjectManager(TResourcePool *resPool) :
		mAccumTime(0.0f),
		mCurCaster(0),
		mCurProjTex(0),
		mResPool(resPool)
	{
		mCasterAlias.push_back("Head_Big_Ears");
		mCasterAlias.push_back("Dwarf");
		mCasterAlias.push_back("Chair");
		mCasterAlias.push_back("TwoBoxes");
		mCasterAlias.push_back("Sphere");
		mCasterAlias.push_back("Cylinder");

		mProjTexAlias.push_back("spotlight");
		mProjTexAlias.push_back("spotlight2");
		mProjTexAlias.push_back("spotlight3");
		mProjTexAlias.push_back("spotlight4");

		for(size_t i=0; i<mCasterAlias.size(); ++i)
			mResPool->Add<IRenderable>(mCasterAlias[i], "../media/mesh/" + mCasterAlias[i] + ".x");

		mResPool->Add<IRenderable>("Floor", "../media/mesh/Floor.x");
		mResPool->Add<IRenderable>("Basis", "../media/mesh/Basis.x");
		mResPool->Add<IRenderable>("Light", "../media/mesh/Light.x");

		mResPool->Add<ITexture>("tiles_d", "../media/texture/tiles_diffuse.dds");
		mResPool->Add<ITexture>("tiles_n", "../media/texture/tiles_normal.dds");
		//mResPool->Add<ITexture>("tiles_d", "../media/texture/stone_diffuse.dds");
		//mResPool->Add<ITexture>("tiles_n", "../media/texture/stone_normal.dds");

		mResPool->Add<ITexture>("white_d", "../media/texture/white_diffuse.dds");
		mResPool->Add<ITexture>("white_n", "../media/texture/white_normal.dds");

		mResPool->Add<ITexture>("object_d", "../media/texture/object_diffuse.dds");
		mResPool->Add<ITexture>("object_n", "../media/texture/object_normal.dds");

		mResPool->Get<ITexture>("tiles_d")->SetFilterMode(ITexture::ANISOTROPY, ITexture::ANISOTROPY, ITexture::ANISOTROPY);
		mResPool->Get<ITexture>("tiles_n")->SetFilterMode(ITexture::ANISOTROPY, ITexture::ANISOTROPY, ITexture::ANISOTROPY);

		mResPool->Get<ITexture>("white_d")->SetFilterMode(ITexture::ANISOTROPY, ITexture::ANISOTROPY, ITexture::ANISOTROPY);
		mResPool->Get<ITexture>("white_n")->SetFilterMode(ITexture::ANISOTROPY, ITexture::ANISOTROPY, ITexture::ANISOTROPY);

		mResPool->Get<ITexture>("object_d")->SetFilterMode(ITexture::ANISOTROPY, ITexture::ANISOTROPY, ITexture::ANISOTROPY);
		mResPool->Get<ITexture>("object_n")->SetFilterMode(ITexture::ANISOTROPY, ITexture::ANISOTROPY, ITexture::ANISOTROPY);

		for(size_t i=0; i<mProjTexAlias.size();++i)
		{
			TStr texName = mProjTexAlias[i];

			mResPool->Add<ITexture>(texName, "../media/texture/" + texName + ".dds");
			mResPool->Get<ITexture>(texName)->SetAddressMode(
				ITexture::CLAMP,
				ITexture::CLAMP,
				ITexture::CLAMP);
		}
	}
	
	//--------------------------------------------------------------------------
	TObjectManager::~TObjectManager()
	{
	}

	//--------------------------------------------------------------------------
	void TObjectManager::Step(float dt)
	{
		mAccumTime += dt;
	}

	//--------------------------------------------------------------------------
	void TObjectManager::NextCasterObject()
	{
		mCurCaster++;

		if( mCurCaster >= mCasterAlias.size() )
			mCurCaster = 0;
	}

	//--------------------------------------------------------------------------
	void TObjectManager::NextProjectiveTexture()
	{
		mCurProjTex++;

		if(mCurProjTex  >= mProjTexAlias.size() )
			mCurProjTex = 0;
	}

	//--------------------------------------------------------------------------
	void TObjectManager::RenderCasterObject(
		render::IRenderer *renderer,
		render::IShader *shader)
	{
		IRenderable *r = mResPool->Get<IRenderable>(mCasterAlias[mCurCaster]);

		TMtx44 rot = mtxRotateY( mAccumTime );
		TMtx44 trans = mtxTranslate(0.0f, -r->GetAABox().getMin()[1], 0.0f);

		identity(rot);

		//renderer->BindTexture(0, mResPool->Get<ITexture>("white_d"));
		//renderer->BindTexture(1, mResPool->Get<ITexture>("white_n"));

		renderer->BindTexture(0, mResPool->Get<ITexture>("object_d"));
		renderer->BindTexture(1, mResPool->Get<ITexture>("object_n"));
		
		renderer->BindTexture(2, mResPool->Get<ITexture>(mProjTexAlias[mCurProjTex]));
		
		renderer->Render(r, rot * trans, shader);
	}

	//--------------------------------------------------------------------------
	void TObjectManager::RenderReceiverObject(
		render::IRenderer *renderer,
		render::IShader *shader)
	{
		TMtx44 world;
		identity(world);

		renderer->BindTexture(0, mResPool->Get<ITexture>("tiles_d") );
		renderer->BindTexture(1, mResPool->Get<ITexture>("tiles_n") );
		renderer->BindTexture(2, mResPool->Get<ITexture>(mProjTexAlias[mCurProjTex]) );
		renderer->Render(mResPool->Get<IRenderable>("Floor"), world, shader);
	}

	//--------------------------------------------------------------------------
	void TObjectManager::RenderBasisVisualization(
		render::IRenderer *renderer,
		render::IShader *shader)
	{
		IRenderable *r = mResPool->Get<IRenderable>("Basis");
		TMtx44 world = mtxTranslate(-10.0f, -r->GetAABox().getMin()[1] + 1.0f, -10.0f);
		renderer->Render(r, world, shader);
	}

	//--------------------------------------------------------------------------
	void TObjectManager::RenderLightVisualization(
		render::IRenderer *renderer,
		render::IShader *shader,
		const TMtx44 &xform)
	{
		IRenderable *r = mResPool->Get<IRenderable>("Light");
		renderer->Render(r, xform, shader);
	}

	//--------------------------------------------------------------------------
}
}
